/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package PhysicCollection;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.JPanel;

/**
 *
 * @author danh.ngothanh
 */
public class AngryBirdsDemo extends JPanel implements MouseListener, MouseMotionListener, Runnable{

//    private Thread mainthread;
    private boolean isrunning;
    private int shotpointx;
    private int shotpointy;
    private int currentmousex;
    private int currentmousey;
    private double shotpower;// == birdvelocityi
    private double shotangle;
    private double virtualtime;
    private int virtualbirdx;
    private int virtualbirdy;
    private double birdvelocityix;
    private double birdvelocityiy;
    private int birdradius;
    private int birddiameter;
        
    private boolean readytoshot;
    private boolean shoted;
    private static int MaxPower = 100;
    private double shottime;
    private int birdcount;
    private int paintbirdcount;
    private int virtualbird_radius;
    private int virtualbird_diameter;
    private double elastic;

    //flag
    private boolean draw_vector, draw_orbit, draw_power, draw_point_instead_line;


    //for debug
    int bird1posx = 0;
    int bird1posy = 0;

    //physic object list
    private ArrayList<PhysicObject> physicobject_list;
    private ArrayList<Point> virtualbirdposition;
    private ArrayList<Point> passed_point_object_list;

    private boolean draw_passed_physic_object;
    private int debug_string_pos_y, debug_string_per_bird_pos_y;

    public AngryBirdsDemo(){
        isrunning = true;
        shotpointx = 0;
        shotpointy = 0;
        currentmousex = 0;
        currentmousey = 0;
        shotpower = 0;
        shotangle = 0;
        virtualtime = 0;
        virtualbirdx = 0;
        virtualbirdy = 0;
        birdvelocityix = 0;
        birdvelocityiy = 0;
        virtualbirdposition = new ArrayList<Point>();        
        readytoshot = false;
        shoted = false;
        shottime = 0;
        birdcount = 0;
        paintbirdcount = 0;
        birdradius = 5;
        birddiameter = 10;
        virtualbird_radius = 2;
        virtualbird_diameter = 4;
        draw_vector = true;
        draw_orbit = true;
        draw_power = true;
        draw_point_instead_line = false;
        elastic = 1.00;
        debug_string_pos_y = 0;

        physicobject_list = new ArrayList<PhysicObject>();
        passed_point_object_list = new ArrayList<Point>();
        
        draw_passed_physic_object = true;

    }

    public class Point{
        private int x;
        private int y;
        public Point(int x, int y){
            this.x = x;
            this.y = y;
        }
        public int getX(){
            return x;
        }
        public int getY(){
            return y;
        }

        public void Destroy(){
            x = 0;
            y = 0;
        }
    }

    public void init(){
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    public void removeAllPhysicObject(){
        for(int i = physicobject_list.size() -1; i >= 0 ; i--){
           physicobject_list.get(i).Destroy();
           physicobject_list.remove(i);
        }
    }

    public void removeAllPassedPoint(){
        for(int i = passed_point_object_list.size() -1; i >= 0 ; i--){
           passed_point_object_list.get(i).Destroy();
           passed_point_object_list.remove(i);
        }
    }

    public void removeAllVirtualBird(){
        while(virtualbirdposition.size() > 0){
            virtualbirdposition.get(0).Destroy();
            virtualbirdposition.remove(0);
        }
    }

    @Override
    public void paint(Graphics g){
        g.setColor(new Color(100, 150, 100));
        g.fillRect(0, 0, getWidth(), getHeight());
        //draw constant
        g.setColor(Color.BLACK);
        debug_string_pos_y = 0;        
        g.drawString("Show Power: " + shotpower, 5, debug_string_pos_y += 15);
        g.drawString("Shot Angle: " + Math.toDegrees(shotangle), 5, debug_string_pos_y += 15);
        g.drawString("PhysicObject Count: " + physicobject_list.size(), 5, debug_string_pos_y += 15);
        if(draw_passed_physic_object)
        g.drawString("Point Count: " + passed_point_object_list.size(), 5, debug_string_pos_y += 15);
//        g.drawString("", 5, debug_string_pos_y += 15);
        if(physicobject_list.size() > 0){
//            g.drawString("PhysicObject PosX: " + physicobject_list.get(physicobject_list.size()-1).getPositionX(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject PosY: " + physicobject_list.get(physicobject_list.size()-1).getPositionY(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject VelocityIniX: " + physicobject_list.get(physicobject_list.size()-1).getVelocityInitX(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject VelocityIniY: " + physicobject_list.get(physicobject_list.size()-1).getVelocityInitY(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject VelocityX: " + physicobject_list.get(physicobject_list.size()-1).getVelocityX(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject VelocityY: " + physicobject_list.get(physicobject_list.size()-1).getVelocityY(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject Power: " + physicobject_list.get(physicobject_list.size()-1).getPositionY(), 5, debug_string_pos_y += 15);
//            g.drawString("PhysicObject Angle: " + physicobject_list.get(physicobject_list.size()-1).getPositionY(), 5, debug_string_pos_y += 15);
        }
        

        //physic object
        g.setColor(Color.BLUE);
        for(int i = 0; i < physicobject_list.size(); i ++){
            g.fillOval(physicobject_list.get(i).getPositionX() - physicobject_list.get(i).getRadius(), physicobject_list.get(i).getPositionY() - physicobject_list.get(i).getRadius(), physicobject_list.get(i).getRadius()*2, physicobject_list.get(i).getRadius()*2);
        }
        
        g.setColor(Color.YELLOW);
        if(draw_power){            
            g.drawLine(shotpointx, shotpointy, currentmousex, currentmousey);
        }

        g.setColor(Color.RED);
        for(int i = 0; i < physicobject_list.size() - 1; i ++){
            for(int j = i + 1; j < physicobject_list.size(); j ++){
                if(Math.sqrt(Math.pow(physicobject_list.get(j).getPositionX() - physicobject_list.get(i).getPositionX(), 2) + Math.pow(physicobject_list.get(j).getPositionY() - physicobject_list.get(i).getPositionY(), 2)) < 2*physicobject_list.get(i).getRadius()){                    
                    g.drawLine(physicobject_list.get(j).getPositionX(), physicobject_list.get(j).getPositionY(), physicobject_list.get(i).getPositionX(), physicobject_list.get(i).getPositionY());
                }
            }
        }

        
        if(draw_orbit){
            if(readytoshot){
                g.setColor(Color.GREEN);
                for(int i = 1; i < virtualbirdposition.size(); i ++){
                    if(draw_point_instead_line)
                        g.fillRect(shotpointx + (int)virtualbirdposition.get(i-1).getX() - virtualbird_radius, shotpointy - (int)virtualbirdposition.get(i-1).getY() - virtualbird_radius, virtualbird_diameter, virtualbird_diameter);
                    else
                        g.drawLine(shotpointx + (int)virtualbirdposition.get(i-1).getX(), shotpointy - (int)virtualbirdposition.get(i-1).getY(), shotpointx + (int)virtualbirdposition.get(i).getX(), shotpointy - (int)virtualbirdposition.get(i).getY());
                }
            }
        }

        //draw vector

        if(draw_vector){
            for(int i = 0; i < physicobject_list.size(); i ++){
                g.setColor(Color.BLACK);
                g.drawLine(physicobject_list.get(i).getPositionX(), physicobject_list.get(i).getPositionY(), physicobject_list.get(i).getPositionX(), physicobject_list.get(i).getPositionY() - (int)physicobject_list.get(i).getVelocityY());
                g.setColor(Color.WHITE);
                g.drawLine(physicobject_list.get(i).getPositionX(), physicobject_list.get(i).getPositionY(), physicobject_list.get(i).getPositionX() + (int)physicobject_list.get(i).getVelocityX(), physicobject_list.get(i).getPositionY());
            }
        }
        
        
        if(draw_passed_physic_object){
            g.setColor(new Color(0, 0, 255, 100));
            for(int i = 0; i < passed_point_object_list.size(); i ++){
                g.fillOval(passed_point_object_list.get(i).getX() - physicobject_list.get(0).getRadius()/2, passed_point_object_list.get(i).getY() - physicobject_list.get(0).getRadius()/2,  physicobject_list.get(0).getRadius()/2*2,  physicobject_list.get(0).getRadius()/2*2);
            }
        }
//        if(physicobject_list.size() > 0)
//        System.out.println(physicobject_list.get(physicobject_list.size() - 1).getPositionY());
//        

//        if(shoted){
//            g.fillOval(shotpointx + birdposx - 5, shotpointy - birdposy - 5, 10, 10);
//        }
//        virtualtime = 0.0;
//        virtualbirdx = (int)(birdvelocityix*virtualtime);
//        virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
//        for(int i = 0; i < 100; i ++){
//            virtualpointarrayx[i] = virtualbirdx;
//            virtualpointarrayy[i] = virtualbirdy;
////            virtualpointarrayx[0] = shotpointx;
////            virtualpointarrayy[0] = shotpointy;
////            virtualtime = (System.currentTimeMillis() - virtualstarttime) * 0.001;
//            virtualtime += 0.5;
//            virtualbirdx = (int)(birdvelocityix*virtualtime);
//            virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
////            g.drawLine(shotpointx + virtualpointarrayx[0], 0, shotpointx, shotpointy);
////            g.drawLine(shotpointx + virtualpointarrayx[0],shotpointy - virtualpointarrayy[0], shotpointx + virtualpointarrayx[1],shotpointy - virtualpointarrayy[1]);
////            g.setColor(Color.GREEN);
////            g.drawLine(shotpointx + virtualpointarrayx[0], shotpointy - virtualpointarrayy[0], shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1]);
////            g.setColor(Color.BLUE);
////            g.drawLine(shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1], shotpointx + virtualpointarrayx[2], shotpointy - virtualpointarrayy[2]);
////            g.setColor(Color.YELLOW);
////            g.drawLine(shotpointx + virtualpointarrayx[2], shotpointy - virtualpointarrayy[2], shotpointx + virtualpointarrayx[3], shotpointy - virtualpointarrayy[3]);
////            g.drawLine(shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1], shotpointx, shotpointy);
//            g.setColor(Color.RED);
//            g.drawLine(shotpointx + virtualpointarrayx[i],shotpointy - virtualpointarrayy[i], shotpointx + virtualbirdx, shotpointy - virtualbirdy);
//        }
//        }

        
    }
    public void run() {
        while(isrunning){
            try{
                Thread.sleep(5);
            }
            catch(Exception e){}
            for(int i = 0; i < physicobject_list.size(); i ++){
                physicobject_list.get(i).Update();                
            }
            if(draw_passed_physic_object && physicobject_list.size() > 0){
                if(((System.currentTimeMillis() - physicobject_list.get(physicobject_list.size() - 1).getReleaseTime()) % 100 < 5) && (passed_point_object_list.size() < 500)){
                    passed_point_object_list.add(new Point(physicobject_list.get(physicobject_list.size() - 1).getPositionX(), physicobject_list.get(physicobject_list.size() - 1).getPositionY()));
                }                
            }


//            virtualtime = (System.currentTimeMillis() - virtualstarttime) * 0.001;
//            virtualbirdx = (int)(birdvelocityix*virtualtime);
//            virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
//            System.out.println("virtualtime == " + virtualtime);
//            System.out.println("virtualbirdy == " + virtualbirdy);            
            repaint();
        }
    }
    public void keyTyped(KeyEvent e) {

    }

    public void keyPressed(KeyEvent e) {
       
    }

    public void keyReleased(KeyEvent e) {

    }
    public void pauseThread(){
        isrunning = false;
    }
    public void resumeThread(){
        isrunning = true;
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mousePressed(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON2){            
            removeAllPhysicObject();
            removeAllPassedPoint();
            removeAllVirtualBird();
            removeAllVirtualBird();
            shotpointx = e.getX();
            shotpointy = e.getY();
            currentmousex = e.getX();
            currentmousey = e.getY();
        }else{
            removeAllVirtualBird();
            shotpower = 0;
            shotangle = 0;
            shotpointx = e.getX();
            shotpointy = e.getY();
            currentmousex = e.getX();
            currentmousey = e.getY();
            readytoshot = true;            
        }        
    }

    public void mouseReleased(MouseEvent e) {
        if(e.getButton() == MouseEvent.BUTTON3){
                shotpower = Math.sqrt((double)((currentmousex - shotpointx)*(currentmousex - shotpointx) + (currentmousey - shotpointy)*(currentmousey - shotpointy)));
                shotangle = Math.atan2((double)(currentmousex - shotpointx), (double)(currentmousey - shotpointy));
                shotangle += Math.toRadians(90);//tang 90 do goc ban bat dau tu phuong ngang
                if(shotpower > MaxPower){
                    shotpower = MaxPower;
                    currentmousex = (int)(shotpointx - (shotpower * Math.cos(shotangle)));
                    currentmousey = (int)(shotpointy + (shotpower * Math.sin(shotangle)));
                }
                removeAllPassedPoint();
                physicobject_list.add(new PhysicObject(shotpointx, shotpointy, shotpower, shotangle));   
        }else if(e.getButton() == MouseEvent.BUTTON1){
            shotpower = Math.sqrt((double)((currentmousex - shotpointx)*(currentmousex - shotpointx) + (currentmousey - shotpointy)*(currentmousey - shotpointy)));
            shotangle = Math.atan2((double)(currentmousex - shotpointx), (double)(currentmousey - shotpointy));
            shotangle += Math.toRadians(90);//tang 90 do goc ban bat dau tu phuong ngang
            if(shotpower > MaxPower){
                shotpower = MaxPower;
                currentmousex = (int)(shotpointx - (shotpower * Math.cos(shotangle)));
                currentmousey = (int)(shotpointy + (shotpower * Math.sin(shotangle)));
            }
            removeAllPassedPoint();            
            physicobject_list.add(new PhysicObject(shotpointx, shotpointy, shotpower, shotangle));
            physicobject_list.get(physicobject_list.size() - 1).setBoundRect(0, 0, getWidth(), getHeight());
        }
    }

    public void mouseEntered(MouseEvent e) {

    }

    public void mouseExited(MouseEvent e) {

    }

    public void mouseDragged(MouseEvent e) {
        currentmousex = e.getX();
        currentmousey = e.getY();
        shotpower = Math.sqrt((double)((currentmousex - shotpointx)*(currentmousex - shotpointx) + (currentmousey - shotpointy)*(currentmousey - shotpointy)));
        shotangle = Math.atan2((double)(currentmousex - shotpointx), (double)(currentmousey - shotpointy));
//        shotpower/=2;//decrease velocityi 2 times.
        shotangle += Math.toRadians(90);//tang 90 do goc ban bat dau tu phuong ngang
        if(shotpower > MaxPower){
            shotpower = MaxPower;
            currentmousex = (int)(shotpointx - (shotpower * Math.cos(shotangle)));
            currentmousey = (int)(shotpointy + (shotpower * Math.sin(shotangle)));
        }
        //calculate x and y initialy velocity
        birdvelocityix = shotpower * Math.cos(shotangle);
        birdvelocityiy = shotpower * Math.sin(shotangle);

        //reset arraylist
        while(virtualbirdposition.size() > 0){
            virtualbirdposition.get(0).Destroy();
            virtualbirdposition.remove(0);
        }
//        System.out.println("virtualbirdposition.size() == " + virtualbirdposition.size());
        int i = 0;
        //begin calculate virtual position
        virtualtime = 0.0;
        virtualbirdx = (int)(birdvelocityix*virtualtime);
        virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
//        while(((shotpointx + virtualbirdx) > 0)||((shotpointx + virtualbirdx) < getWidth())||((shotpointy - virtualbirdy) < getHeight())){
//         while((shotpointy - virtualbirdy) < getHeight()){
//            if(virtualbirdposition.size()<100){
//            while((shotpointy - virtualbirdy) < getHeight()+getHeight()/8){
            while((shotpointy - virtualbirdy) < getHeight()){
                virtualbirdposition.add(new Point(virtualbirdx, virtualbirdy));
                if(draw_point_instead_line)
                    virtualtime += 1;
                else
                    virtualtime += 0.005;
                virtualbirdx = (int)(birdvelocityix * virtualtime);
                virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
                i++;
//            }else{
//                System.out.println("Out of memory");
//             }
        }
        virtualbirdposition.add(new Point(virtualbirdx, virtualbirdy));

//        System.out.println("virtualbirdposition.size() == " + virtualbirdposition.size());
//        for(i = 0; i < virtualbirdposition.size(); i ++){
//            System.out.println("virtualbirdpositionx["+i+"] == " + virtualbirdposition.get(i).getPosX() +", virtualbirdpositiony["+i+"] == " + virtualbirdposition.get(i).getPosY());
//        }
//        for(int i = 0; i < 100; i ++){
//            virtualpointarrayx[i] = virtualbirdx;
//            virtualpointarrayy[i] = virtualbirdy;
////            virtualpointarrayx[0] = shotpointx;
////            virtualpointarrayy[0] = shotpointy;
////            virtualtime = (System.currentTimeMillis() - virtualstarttime) * 0.001;
//            virtualtime += 0.5;
//            virtualbirdx = (int)(birdvelocityix*virtualtime);
//            virtualbirdy = (int)(birdvelocityiy * virtualtime + 0.5 * (-9.8) * virtualtime * virtualtime);
////            g.drawLine(shotpointx + virtualpointarrayx[0], 0, shotpointx, shotpointy);
////            g.drawLine(shotpointx + virtualpointarrayx[0],shotpointy - virtualpointarrayy[0], shotpointx + virtualpointarrayx[1],shotpointy - virtualpointarrayy[1]);
////            g.setColor(Color.GREEN);
////            g.drawLine(shotpointx + virtualpointarrayx[0], shotpointy - virtualpointarrayy[0], shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1]);
////            g.setColor(Color.BLUE);
////            g.drawLine(shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1], shotpointx + virtualpointarrayx[2], shotpointy - virtualpointarrayy[2]);
////            g.setColor(Color.YELLOW);
////            g.drawLine(shotpointx + virtualpointarrayx[2], shotpointy - virtualpointarrayy[2], shotpointx + virtualpointarrayx[3], shotpointy - virtualpointarrayy[3]);
////            g.drawLine(shotpointx + virtualpointarrayx[1], shotpointy - virtualpointarrayy[1], shotpointx, shotpointy);
//        }

        repaint();
    }

    public void mouseMoved(MouseEvent e) {
        
    }
}
